import json
import random
import re
from django import http
from django.contrib.auth import login, authenticate, logout
from django.core.serializers import serialize
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection
from tenement_project.libs.captcha.captcha import captcha
from tenement_project.utils import constants
from tenement_project.utils.fastdfs.new_upavatar import up_avatar, qiliuyun_avatar
from tenement_project.utils.response_code import RET
from users.models import User

from django.core.files.uploadedfile import InMemoryUploadedFile, UploadedFile


# class RedirectLoginView(View):
#     def get(self, request):
#         return HttpResponseRedirect("/login.html/")


# 图片验证码
class ImageCodeView(View):
    def get(self, request):
        cur = request.GET.get("cur")  # 验证码编号
        pre = request.GET.get("pre")  # 上一次验证码编号

        if not all([cur, cur]):
            return http.HttpResponseForbidden("参数不全")

        _, text, image = captcha.generate_captcha()
        print(text)
        # 保存图片验证码
        redis_conn = get_redis_connection('code')
        redis_conn.setex('img_%s' % cur, constants.REDIS_IMAGE_CODE_EXPIRES, text)
        # 响应图片验证码
        return http.HttpResponse(image, content_type='image/jpg')


# 短信验证码
class SMSCodeView(View):
    def post(self, request):
        data_dict = json.loads(request.body.decode())
        mobile = data_dict["mobile"]  #
        id = data_dict["id"]  # 图片验证码编号
        image_text = data_dict["text"]  # 图片验证码内容

        # 校验参数
        if not all([mobile, id, image_text]):
            return http.JsonResponse({"errno": RET.DATAERR, "errmsg": "缺少参数"})
        if not re.match('^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({"errno": RET.DATAERR, "errmsg": "手机号码格式错误"})
        # 判断手机号有没有被注册过
        if User.objects.filter(mobile=mobile):
            return http.JsonResponse({"errno": RET.DBERR, "errmsg": "手机号已被注册"})

        redis_conn = get_redis_connection('code')
        pipeline = redis_conn.pipeline()
        redis_cli_code = redis_conn.get('img_%s' % id)
        redis_cli_code = redis_cli_code.decode()
        if image_text.upper() != redis_cli_code.upper():
            return http.JsonResponse({'errno': RET.DATAERR, 'errmsg': '图形验证码错误'})
        if not redis_cli_code:
            return http.JsonResponse({'errno': RET.DATAERR, 'errmsg': '图片验证码已过期'})

        # 改良代码 不会重复生成短信验证码
        redis_conn = get_redis_connection('code')
        pipeline = redis_conn.pipeline()
        redis_cli_flag = redis_conn.get("redis_cli_flag%s" % mobile)  # 将手机号码打上标记，防止频繁发送短信验证码
        if redis_cli_flag:
            return http.JsonResponse({"errno": RET.REQERR, "errmsg": "请勿频繁发送短信"})
        else:
            sms_code = '%06d' % random.randint(0, constants.SMS_CODE_EXPIRES)
            print(sms_code)
            # 3,1 设置标记,防止1分钟之内, 短信多次发送
            pipeline.set("sms_code_%s" % mobile, sms_code, constants.REDIS_SMS_CODE_EXPIRES)  # 将短信验证码存入redis留作判断是否正确
            # 发送验证码
            # from celery_tasks.sms.tasks import send_message  # 等待调试
            # send_message.delay(mobile, sms_code)
            pipeline.set("redis_cli_flag%s" % mobile, 1, constants.REDIS_MOBILE_SMS_CODE_EXPIRES)
            pipeline.execute()  # 最后通过pipeline管道提交数据的redis
            context = {
                'errno': RET.OK,
                'errmsg': '发送短信成功',
            }
            return http.JsonResponse(context)


# 注册
class RegisterView(View):
    def post(self, request):
        data_dict = json.loads(request.body.decode())
        mobile = data_dict["mobile"]
        phonecode = data_dict["phonecode"]
        password = data_dict["password"]

        # 校验参数
        if not all([mobile, phonecode, password]):
            return http.JsonResponse({"errno": RET.DATAERR, "errmsg": "缺少参数"})
        if not re.match('^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({"errno": RET.DATAERR, "errmsg": "手机号码格式错误"})
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}', password):
            return http.JsonResponse({"errno": RET.DATAERR, "errmsg": "密码格式错误"})

        redis_conn = get_redis_connection("code")
        redis_cli_sms = redis_conn.get("sms_code_%s" % mobile)  # 将手机号码打上标记，防止频繁发送短信验证码
        if phonecode != redis_cli_sms.decode():
            return http.JsonResponse({"errno": RET.DATAERR, "errmsg": "短信验证码错误"})

        try:
            # 手机作为用户名
            User.objects.create_user(username=mobile, password=password, mobile=mobile)
        except Exception as e:
            return http.JsonResponse({"errno": RET.DATAERR, "errmsg": "注册失败"})

        return http.JsonResponse({"errno": RET.OK, "errmsg": "注册成功"})


# 登录
class LoginView(View):
    def get(self, request):
        if request.user.is_authenticated:
            context = {"errno": RET.OK,
                       "errmsg": "已登录",
                       "data": {
                           "user_id": request.user.id,
                           "name": request.user.username
                       }
                       }
            return http.JsonResponse(context)
        else:
            context = {
                "errno": "4101",
                "errmsg": "未登录"
            }
            return http.JsonResponse(context)

    def post(self, request):
        data_dict = json.loads(request.body.decode())
        mobile = data_dict["mobile"]
        password = data_dict["password"]

        # 校验参数
        if not all([mobile, password]):
            return http.JsonResponse({"errno": RET.DATAERR, "errmsg": "用户或密码未填写"})

        # 为避免浪费数据库资源 先判断格式是否正确 可要可不要
        if not re.match('^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({"errno": RET.DATAERR, "errmsg": "手机号码格式错误"})
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}', password):
            return http.JsonResponse({"errno": RET.DATAERR, "errmsg": "密码格式错误"})
        user = authenticate(username=mobile, password=password)  # 这句代处理
        if not user:
            return http.JsonResponse({"errno": RET.DBERR, "errmsg": "用户名或密码错误"})
        login(request, user)  # 就是将用户的信息存储在redis-session
        request.session.set_expiry(constants.LOGIN_EXPIRES)  # 保持登录两天
        # request.get_signed_cookie('mobile', user.username, max_age=constants.USER_LOGIN_COOKIE_EXPIRES)
        return http.JsonResponse({"errno": RET.OK, "errmsg": "登录成功"})

    def delete(self, request):
        # 清除session
        logout(request)
        return http.JsonResponse({"errno": RET.OK, "errmsg": "退出登录"})


# 个人中心
class UserInfoView(View):
    def get(self, request):
        if request.user.is_authenticated:
            try:
                avatar = request.user.avatar.url,
            except Exception as e:
                avatar = None
            context = {"errno": RET.OK,
                       "errmsg": "已登录",
                       "data": {
                           "avatar_url": avatar,
                           "name": request.user.username,
                           "mobile": request.user.mobile
                       }
                       }
            return http.JsonResponse(context)
        else:
            context = {
                "errno": RET.SESSIONERR,
                "errmsg": "未登录"
            }
            return http.JsonResponse(context)


# 上传照片
class AvatarUpView(View):
    def post(self, request):
        if request.user.is_authenticated:
            data_dict = request.FILES
            avatar_data = data_dict["avatar"]
            # up_avatar(avatar_data.read(), request)  # 上传照片
            qiliuyun_avatar(avatar_data, request)
            context = {"errno": RET.OK,
                       "errmsg": "已登录",
                       "data": {
                           "avatar_url": request.user.avatar.url,
                           "name": request.user.username,
                           "mobile": request.user.mobile
                       }
                       }
            return http.JsonResponse(context)
        else:
            context = {
                "errno": RET.SESSIONERR,
                "errmsg": "未登录"
            }
            return http.JsonResponse(context)


# 修改用户名
class UsernameUpView(View):
    def put(self, request):
        if request.user.is_authenticated:
            data_dict = json.loads(request.body.decode())
            username = data_dict["name"]
            # 校验用户填写的用户名
            if not username:
                return http.JsonResponse({"errno": RET.DATAERR, "errmsg": "未填写用户名"})
            if len(username) > 10:  # 用户名可填写汉字
                return http.JsonResponse({"errno": RET.DATAERR, "errmsg": "用户名过长"})
            request.user.username = username
            request.user.save()
            context = {"errno": RET.OK,
                       "errmsg": "用户名修改成功",
                       "data": {
                           "user_id": request.user.id,
                           "name": request.user.username
                       }
                       }
            return http.JsonResponse(context)
        else:
            context = {
                "errno": RET.SESSIONERR,
                "errmsg": "未登录"
            }
            return context


# 实名验证
class UserAuthView(View):
    def get(self, request):
        if request.user.is_authenticated:
            real_name = request.user.real_name
            id_card = request.user.id_card
            if real_name and id_card:
                context = {"errno": RET.OK,
                           "errmsg": "已验证",
                           "data": {
                               "real_name": real_name,
                               "id_card": id_card
                           }
                           }
                return http.JsonResponse(context)

            else:
                context = {"errno": RET.DBERR,
                           "errmsg": "未实名验证",
                           "data": {
                               "real_name": None,
                               "id_card": None
                           }
                           }
                return http.JsonResponse(context)

        else:
            context = {
                "errno": RET.SESSIONERR,
                "errmsg": "未登录"
            }
            return http.JsonResponse(context)

    def post(self, request):
        user = request.user
        if user.is_authenticated:
            data_dict = json.loads(request.body.decode())
            real_name = data_dict["real_name"]
            id_card = data_dict["id_card"]

            if not all([real_name, id_card]):
                return http.JsonResponse({"errno": RET.DATAERR, "errmsg": "真实姓名或身份证号码未填写"})
            # 姓名正则表达式
            # if not re.match(r'[\u4E00-\u9FA5]{2,5}', real_name):
            if len(real_name) > 5:
                return http.JsonResponse({"errno": RET.DATAERR, "errmsg": "姓名格式错误"})
            # 身份证正则 15 位 或者 18 位
            if not re.match(
                    "^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$",
                    id_card) or re.match("^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}$",
                                         id_card):
                return http.JsonResponse({"errno": RET.DATAERR, "errmsg": "身份证格式错误"})
            user.id_card = id_card
            user.real_name = real_name
            user.save()
            return http.JsonResponse({"errno": RET.OK, "errmsg": "实名验证成功"})
        else:
            context = {
                "errno": RET.SESSIONERR,
                "errmsg": "未登录"
            }
            return http.JsonResponse(context)

# Create your views here.
